#include<stdlib.h>
#include<stdio.h>
#include <pthread.h>
#include "ConfigStruct.h"
#include <time.h>
#include <unistd.h>
#include <stdint.h>

void call_threads();
void *thread_controller( struct ConfigStruct config );


int main(int argc, char ** argv)
{
	struct ConfigStruct configuration;


	if(argc != 2)
	{
		printf("Usage:\t");
		printf("test <config_file>\n");
		return;
	}

	printf("Using config file: %s\n", argv[1]);

	ReadConfig(argv[1], &configuration);

	/*
	   printf("laddress: %s\n", configuration.laddress);
	   printf("raddress: %s\n", configuration.raddress);
	   printf("num_rounds: %d\n", configuration.num_rounds);
	   printf("packet_size: %d\n", configuration.packet_size);
	   printf("num_tests: %d\n", configuration.num_tests);
	   printf("test_to_run: %s\n", configuration.test_to_run);
	   */


	call_threads(configuration);


}


void call_threads(struct ConfigStruct config)
{
	int i;

	for(i = 0; i < config.num_tests; i ++)
	{
		thread_controller(config);
	}

}
 
void *thread_controller( struct ConfigStruct config )
{

	if(strstr(config.test_to_run, "sping") != NULL)
	{
		run_sping(&config);
	}
	else if(strstr(config.test_to_run, "sp_uflooder") != NULL ||strstr(config.test_to_run, "sp_tflooder") != NULL)
	{

		run_flooder(&config);
	}
    else
    {

		run_short_flooder(&config);
    }
}

void run_short_flooder(struct ConfigStruct *config)
{
    struct timespec time1;
    struct timespec time2;
    char command[1000];
    char temp[10];
    strcpy(command, config->test_to_run);
    strcat(command, " -a ");
    strcat(command, config->raddress);
    strcat(command, " -s ");
    strcat(command, " -v ");
    strcat(command, " -n ");
    sprintf(temp, "%d", config->num_rounds);
    strcat(command, temp);
    strcat(command, " > ");
    strcat(command, " log");

    sprintf(temp, "%d", config->thread_id);
    strcat(command, temp);

    strcat(command, ".txt");
    strcat(command, "\n");
    printf("command is\n%s\n", command);   


    clock_gettime(CLOCK_MONOTONIC, &time1);
    	system(command);
    clock_gettime(CLOCK_MONOTONIC, &time2);

    struct timespec difference;
    diff(time1, time2, &difference);
    printf("The execution took: %d seconds, %d nanoseconds\n",difference.tv_sec,  difference.tv_nsec);
}
void run_flooder(struct ConfigStruct *config)
{
    struct timespec time1;
    struct timespec time2;
    char command[1000];
    char temp[10];
    strcpy(command, config->test_to_run);
    strcat(command, " -a ");
    strcat(command, config->raddress);
    strcat(command, " -o ");
    strcat(command, config->laddress);
    strcat(command, " -s ");
    strcat(command, " -v ");
    strcat(command, " -n ");
    sprintf(temp, "%d", config->num_rounds);
    strcat(command, temp);
    strcat(command, " > ");
    strcat(command, " log");

    sprintf(temp, "%d", config->thread_id);
    strcat(command, temp);

    strcat(command, ".txt");
    strcat(command, "\n");
    printf("command is\n%s\n", command);   


    clock_gettime(CLOCK_MONOTONIC, &time1);
    	system(command);
    clock_gettime(CLOCK_MONOTONIC, &time2);

    struct timespec difference;
    diff(time1, time2, &difference);
    printf("The execution took: %d seconds, %d nanoseconds\n",difference.tv_sec,  difference.tv_nsec);
}

void run_sping(struct ConfigStruct *config)
{
	struct timespec time1, time2;
    char command[1000];
    char temp[10];
    strcpy(command, config->test_to_run);
    strcat(command, " -a ");
    strcat(command, config->raddress);
    strcat(command, " -l ");
    strcat(command, config->laddress);
    strcat(command, " -s ");
    strcat(command, " -n ");
    sprintf(temp, "%d", config->num_rounds);
    strcat(command, temp);
    strcat(command, " > ");
    strcat(command, " log");

    sprintf(temp, "%d", config->thread_id);
    strcat(command, temp);

    strcat(command, ".txt");
    strcat(command, "\n");
    printf("command is\n%s\n", command);   

    clock_gettime(CLOCK_MONOTONIC, &time1);
    system(command);
    clock_gettime(CLOCK_MONOTONIC, &time2);

    printf("The execution took: %d seconds, %d nanoseconds\n",time2.tv_sec - time1.tv_sec,  time2.tv_nsec - time1.tv_nsec);
}

void diff(struct timespec start, struct timespec end, struct timespec *result)
{
    if ((end.tv_nsec-start.tv_nsec)<0) {
        result->tv_sec = end.tv_sec-start.tv_sec-1;
        result->tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
    } else {
        result->tv_sec = end.tv_sec-start.tv_sec;
        result->tv_nsec = end.tv_nsec-start.tv_nsec;
    }
}
